package com.xuzy.x808.server.protocol.parser;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

/**
 * 按照808协议中标识位的设计：
 * 采用 0x7e 表示，若校验码、消息头以及消息体中出现 0x7e，则要进行转义处理，转义
 * 规则定义如下：
 * 0x7e <————> 0x7d 后紧跟一个 0x02；
 * 0x7d <————> 0x7d 后紧跟一个 0x01。
 * 转义处理过程如下：
 * 发送消息时：消息封装——>计算并填充校验码——>转义；
 * 接收消息时：转义还原——>验证校验码——>解析消息。
 * 示例：
 * 发送一包内容为 0x30 0x7e 0x08 0x7d 0x55 的数据包，则经过封装如下：0x7e 0x30 7d 0x02 0x08 0x7d
 * 0x01 0x55 0x7e。
 * <p>
 * 也就是说，我们需要将报文中封装后的数据进行还原，即0x7e 0x30 7d 0x02 0x08 0x7d
 * * 0x01 0x55 0x7e 还原为 0x30 0x7e 0x08 0x7d 0x55 的数据包才是我们需要的真实报文
 */
public class MsgParser {

    /**
     * 还原数据包
     *
     * @param byteBuf 去除了头尾标识位之后的报文
     * @return
     */
    public static ByteBuf restore0x7D(ByteBuf byteBuf) {
        int length = byteBuf.readableBytes();
        int lastIndex = 0;
        ByteBuf result = Unpooled.buffer(1024);

        for (int i = 0; i < length; i++) {
            if (byteBuf.getByte(i) == (byte) 0x7D) {
                if (byteBuf.getByte(i + 1) != (byte) 0x01
                        && byteBuf.getByte(i + 1) != (byte) 0x02) {
                    return null;
                }
                result.writeBytes(byteBuf.slice(lastIndex, i - lastIndex));
                lastIndex = i + 2;
                if (byteBuf.getByte(i + 1) == (byte) 0x01) {
                    result.writeByte(0x7D);
                }
                if (byteBuf.getByte(i + 1) == (byte) 0x02) {
                    result.writeByte(0x7E);
                }
            }
        }
        result.writeBytes(byteBuf.slice(lastIndex, length - 1 - lastIndex + 1));
        return result;
    }

}

